eslint-plugin-prettier を ESLint から 分離するサンプル – Intellij IDEA の設定変更も
すでにこちらの方の解説ブログもありますが、ESLint と Prettier を組み合わせる場合の推奨方法が変わりました。
Prettier と ESLint の組み合わせの公式推奨が変わり plugin が不要になった
本稿では リポジトリに適用してみて Before/After を具体的に見ていきます。
TL;DR
エディタが ESLint にも Prettier にも対応しているならば ESLint から eslint-plugin-prettier を除外し、ESLint と Prettier が個別に実行されるようにする。
コンテンツ
- 推奨がどう変わったか
- どこをどう変更すればよいか
- Intellij IDEA / WebStorm の場合、どの設定を変更すればよいか
推奨がどう変わったか
Prettier はもともと ESLint のプラグインとしても使うことができました。多くのエディタが eslint --fix
をサポートしていることから、長らく eslint --fix
のついでに整形も行うような形がとられていました。しかし、VSCode や JetBrains が Prettier を個別に実行できるようになり、
- ESLint のような静的解析ツールの自動修正機能
- コードフォーマッタである Prettier
これらを個別で実行するようにしてほしい、と変わったようです。Linterとの統合について述べている、こちらのドキュメントを見ます。
Integrating with Linters · Prettier
Prettier vs. Linters · Prettier
意訳すると以下のようなメッセージだと解釈しています。
- 静的解析ツールである ESLint と、コードフォーマッタである Prettier は本来分けて考えるべきもの
- ただ、Prettier が出たばかりのときは、エディタが Prettier に対応しておらず、ESLint のプラグインとしてフォーマットを実行できることには意味があった
- Prettier に対応しているエディタも増えてきた。以下のような理由もあるので Linterのプラグインとしてではなく、Prettier 単体で実行してほしい:
- 静的解析ツールのプラグインとしてフォーマッタを当てると、エディターに赤い波線がたくさん表示され、煩わしくなる
- Prettierを直接実行するよりも遅い
- 不整合が起きる可能性がある
どこをどう変更すればよいか
大きく、
eslint.rc.js
からeslint-plugin-prettier
を除去するpackage.json
のスクリプトでeslint --fix
相当のことをやっていた箇所でeslint --fix && prettier --write
に変更する
これらを変更します。
実際に分離した例
TypeScript のバリデータライブラリで試しました。差分のプルリクエストはこちらです。説明用のサンプルとして使います。
fix formatter by cm-wada-yusuke · Pull Request #6 · cm-madlabs/ts-validator
eslint.rc.js
から eslint-plugin-prettier
を除去する
module.exports = { env: { node: true, }, parser: '@typescript-eslint/parser', plugins: ['node', '@typescript-eslint'], parserOptions: { sourceType: 'module', }, rules: { semi: 'off', '@typescript-eslint/semi': ['error'], // `export` functions may be listed first. '@typescript-eslint/no-use-before-define': [ 'error', { functions: true, classes: false, variables: true }, ], // To read environment variables. '@typescript-eslint/no-non-null-assertion': 'off', // Disable the eslint side because it conflicts with the prettier. '@typescript-eslint/indent': 'off', // Parameter functions return type is obvious and need not to be explicit. '@typescript-eslint/explicit-function-return-type': [ 'error', { allowExpressions: true, allowTypedFunctionExpressions: true, allowHigherOrderFunctions: true, }, ], }, extends: [ 'eslint:recommended', 'plugin:@typescript-eslint/eslint-recommended', 'plugin:@typescript-eslint/recommended', 'plugin:prettier/recommended', // 消す 'prettier', // 追加する ], };
これで eslint --fix
では prettier が走らないようになります。
'prettier' は必要?
必要だと思います。たいていの場合、 eslint-plugin-prettier
とは別に、ESLint で Prettier と競合するルールを無視するための eslint-config-prettier もインストールされているはずです。競合の回避は必要なので、 ESLintで有効にするため prettier
に書き換えます。これで、競合を回避するための設定だけが引き続き ESLint で利用できます。
package.json
を修正する
{ "name": "@cm-madlabs/ts-validator", "version": "1.0.3", "description": "true/false generic validator", "main": "dist/index.js", "types": "dist/index.d.ts", "author": "waddy", "license": "MIT", "private": false, "publishConfig": { "access": "public" }, "keywords": [ "TypeScript", "Validator" ], "bugs": { "url": "https://github.com/team-mad/ts-validator/issues" }, "homepage": "https://github.com/team-mad/ts-validator#typescript-validator", "scripts": { "build": "tsc -p tsconfig.json", "build:doc": "typedoc", "test": "jest", "test:coverage": "yarn jest --coverage", "lint": "eslint './{lib,src,test}/**/*.{ts,tsx}'", "lint-fix": "eslint --fix './{lib,src,test}/**/*.{ts,tsx}' && prettier --write './{lib,src,test}/**/*.{ts,tsx}'", "lint-staged": "lint-staged", "clean": "shx rm -rf ./dist && shx rm -rf './{src}/**/*.js' && shx rm -rf './{src}/**/*.d.ts'" }, "husky": { "hooks": { "pre-commit": "lint-staged" } }, "lint-staged": { "*.ts": [ "yarn run lint-fix", "yarn run lint", "git add" ] }, "dependencies": { "luxon": "^1.25.0" }, "devDependencies": { "@types/luxon": "^1.25.0", "@typescript-eslint/eslint-plugin": "^4.4.1", "@typescript-eslint/parser": "^4.4.1", "codecov": "^3.8.0", "eslint": "^7.11.0", "eslint-config-prettier": "^6.12.0", "eslint-plugin-node": "^11.1.0", "husky": "^4.3.0", "jest": "^26.5.3", "jest-coverage-badges": "^1.1.2", "lint-staged": "^10.4.0", "prettier": "^2.1.2", "shx": "^0.3.2", "ts-jest": "^26.4.1", "ts-node": "^9.0.0", "typedoc": "^0.19.2", "typescript": "^4.0.3" } }
eslint --fix './{lib,src,test}/**/*.{ts,tsx}' && prettier --write './{lib,src,test}/**/*.{ts,tsx}'
のように、どちらも明示的に修正が走るようにします- dependencies から
eslint-plugin-prettier
を消します eslint-config-prettier
は消しません
yarn lint-fix
の結果は変えずに、ESLint と Prettier を分離できました。
Intgllij IDEA で prettier フォーマッタが走るようにする
最後はエディタの設定です。これまでは、Intellijで eslint --fix
相当の自動フォーマットを走らせれば Prettier も動作させることができました。
追加して、Prettier も走らせられるようにします。
これでフォーマット時に Prettier による整形も実行できます。完全に余談ですが私は「フォーマット」と「保存」は明確に分けて実行したいので保存時にフォーマットする設定は無効にしています。作業を中断する場合など、あえて文法エラーを残して保存しコンテキストを維持する…といった目的です。
まとめ
エディタでPrettierを実行できるようになり、ESLint と Prettier は個別に設定・適用することが推奨されています。本稿がどなたかの参考になれば幸いです。
ソースコード
fix formatter by cm-wada-yusuke · Pull Request #6 · cm-madlabs/ts-validator